﻿using System;
using System.Collections.Generic;
using System.Linq;
using CoreLibrary;
using CoreLibrary.Date;
using CoreLibrary.Paging;
using CoreLibrary.Service;
using Entities.DataBase;
using Entities.DataBase.Obj;
using Entities.DataBase.Persistent;
using Entities.Enumeration;
using Modules.Tracking;
using WebService.Email;
using WebService.Security;
using WebService.Service.Transfer;

using Order = Entities.DataBase.Persistent.Order;

namespace WebService.Service {

    public class OrderServiceX : AbstractService, IOrderServiceX {

        public bool CreateOrder(string passport, CreateOrderRequest request) {
            return Run(passport, token => {

                var totalPrice   = (decimal)request.OrderItems.Sum(item => item.Price * item.Count);
                var totalCost    = (decimal)request.OrderItems.Sum(item => item.Cost  * item.Count);
                var orderPostage = (decimal)request.OrderPostage;
                var totalPostage = (decimal)request.OrderItems.Sum(item => item.Postage * item.Count) +
                                   (decimal)request.OrderPostage;

                var guid = GuidUtil.GuidN();
                var avgOrderPostage = request.OrderPostage / request.OrderItems.Sum(item => item.Count);

                Locate<IOrderRepository>().Create(new Order {
                    Guid         = guid,
                    CourierId    = request.CourierId,
                    TrackingId   = request.TrackingId,
                    OperatorId   = token.UserId,
                    CustomerId   = request.CustomerId,
                    OrderPostage = orderPostage,
                    TotalPostage = totalPostage,
                    Cost         = totalCost,
                    Price        = totalPrice,
                    Profit       = (decimal) CalcProfit(request.OrderItems, request.OrderPostage, request.CurrentRate),
                    Rate         = (decimal) request.CurrentRate,
                    Description  = StringUtil.Join("<br/>", request.OrderItems, CreateOrderDescription),
                    DateCreated  = request.DateOrdered ?? DateTime.UtcNow, 
                    Status       = string.IsNullOrEmpty(request.TrackingId) 
                                 ? OrderStatus.Pending 
                                 : OrderStatus.Shipping
                }, request.OrderItems.Select(item => new OrderRecord {
                    StockId                 = item.StockId,
                    OrderId                 = guid,
                    ProductId               = item.ProductId,
                    Cost                    = (decimal) item.Cost,
                    CostCurrency            = item.CostCurrency,
                    Postage                 = (decimal) item.Postage,
                    PostageCurrency         = item.PostageCurrency,
                    AvgOrderPostage         = (decimal) avgOrderPostage,
                    AvgOrderPostageCurrency = Currency.AUD.Name,
                    CustomerId              = request.CustomerId,
                    Price                   = (decimal) item.Price,
                    PriceCurrency           = item.PriceCurrency,
                    Count                   = item.Count,
                }).ToList());

                if (request.CourierId != Courier.Other.Code) {
                    var customer  = Locate<ICustomerRepository>().Get(request.CustomerId);
                    var packageId = GuidUtil.GuidN();
                    Locate<IPackageRepository>().Add(new Package {
                        Id              = packageId,
                        DateCreated     = request.DateOrdered ?? DateTime.UtcNow, 
                        CourierId       = request.CourierId,
                        Type            = PackageType.Order.Type,
                        TrackingId      = Util.GetString(request.TrackingId),
                        Description     = StringUtil.Join("<br/>", request.OrderItems, CreateOrderDescription),
                        Recipient       = Util.GetString(customer.CName),
                        Reference       = Util.GetString(guid),
                        PhoneNumber     = Util.GetString(request.PhoneNumber),
                        ShippingAddress = Util.GetString(request.ShippingAddress),
                        Status          = string.IsNullOrEmpty(request.TrackingId)
                                        ? PackageStatus.PENDING
                                        : PackageStatus.SHIPPING,
                    });
                }

                EmailManager.SendEmail(new CreateOrderRequestTemplate {
                    Name    = token.FirstName + " " + token.LastName,
                    Request = request
                });

                return true;
            });
        }

        public bool CancelOrder(string passport, int orderId) {
            return Run(passport, token => {
                var order = Locate<IOrderRepository>().Get(orderId);
                Locate<IOrderRepository>().Remove(orderId);
                Locate<IPackageRepository>().RemoveByReference(order.Guid);

                EmailManager.SendEmail("订单删除", token.FirstName + "刚刚删除了订单: " + orderId);
                return true;
            });
        }

        public bool UpdateOrder(string passport, UpdateOrderRequest request) {
            return Run(passport, token => {
                Locate<IOrderRepository>().Update(request.OrderId, new OrderUpdator {
                    Postage    = request.Postage,
                    Price      = request.Price,
                    CourierId  = request.CourierId,
                    TrackingId = Util.GetString(request.TrackingId),
                });
                return true;    
            });
        }

        public bool UpdateOrderStatus(string passport, int orderId, int status) {
            return Run(passport, token => {
                var order = Locate<IOrderRepository>().Get(orderId);
                Locate<IOrderRepository>().UpdateStatus(orderId, status);

                var packages = Locate<IPackageRepository>().ListByReference(order.Guid);
                foreach (var packageInfo in packages) {
                    if (status == OrderStatus.Complete) {
                        Locate<IPackageRepository>().UpdateStatus(packageInfo.Id, PackageStatus.DELIVERED);    
                    }
                    else if (status == OrderStatus.Shipping) {
                        Locate<IPackageRepository>().UpdateStatus(packageInfo.Id, PackageStatus.SHIPPING);  
                    }
                    else if (status == OrderStatus.Pending) {
                        Locate<IPackageRepository>().UpdateStatus(packageInfo.Id, PackageStatus.PENDING);
                    }
                }
                return true;
            });
        }

        public string TrackOrder(string passport, int orderId) {
            return Run(passport, token => {
                var order = Locate<IOrderRepository>().Get(orderId);
                if (string.IsNullOrEmpty(order.TrackingId)) {
                    return "没有找到包裹查询号码，当前包裹可能并未投递。";
                }

                var result = Locate<IShipmentService>().Track(new TrackRequest {
                    TrackId   = order.TrackingId,
                    CourierId = order.CourierId,
                    DateTrack = DateTime.UtcNow
                });

                if (!result.Succeed) {
                     return "查询失败： "+ result.ErrorMessage;
                }

                return result.Data;
            });
        }

        public PagingResult<OrderInfo> ListOrders(string passport, PagingRequest request) {
            return Run(passport, token => {
                var orders = Locate<IOrderRepository>().ListAll();
                return new PagingResult<OrderInfo> {
                       Offset = request.Offset,
                       Total  = orders.Count,
                       Data   = orders.Skip(request.Offset)
                                      .Take(request.Limit)
                                      .ToList()
                };
            });
        }

        public PagingResult<OrderInfo> SearchOrders(string passport, SearchOrderRequest request) {
            return Run(passport, token => {
                var dateBegin = request.DateFrom ?? DateUtil.Epoch;
                var dateEnd   = request.DateTo   ?? DateTime.UtcNow;

                var orders = Locate<IOrderRepository>().SearchOrders(new SearchOrderReq {
                        Status       = request.Status,
                        CustomerName = Util.GetString(request.CustomerName),
                        CourierId    = request.CourierId,
                        DateFrom     = dateBegin,
                        DateTo       = dateEnd,
                });

                return new PagingResult<OrderInfo> {
                    Offset = request.Offset,
                    Total  = orders.Count,
                    Data   = orders.Skip(request.Offset)
                                   .Take(request.Limit)
                                   .ToList()
                };
            });
        }

        private static string CreateOrderDescription(OrderItem item) {
            return "产品:" + Util.GetString(item.ProductName) + "数量: (" + item.Count + ")";
        }

        private static double CalcProfit(List<OrderItem> orderItems, double orderPostage, double rate) {
            var totalPrice    = orderItems.Sum(item => item.Price   * item.Count);
            var totalCost     = orderItems.Sum(item => item.Cost    * item.Count * rate);
            var totalPostage  = orderItems.Sum(item => item.Postage * item.Count * rate) + orderPostage * rate;
            return totalPrice - (totalCost + totalPostage);
        }

        protected static void CheckPermission(UserToken token, int orderId) {
            var transaction = Services.Locate<IOrderRepository>().Get(orderId);
            if (!token.UserId.Equals(transaction.OperatorId)) {
                 throw ServiceErrors.CreateUnauthorisedException("这个交易不是由您创建的, 您没有权限处理这个交易， 请联系交易创建人");
            }
        }

       
    }
}
